/*
    Epoll 封装
*/

#pragma once

#include "nocopy.hpp"

#include <sys/epoll.h>

#include <cstring>

#include "log.hpp"

class Epoller : public nocopy // 防止拷贝 继承防拷贝类 class nocopy
{
    static const int _size = 1024;

public:
    Epoller()
    {
        int size = 128;
        _epfd = epoll_create(_size); // 创建 epoll 模型
        if (_epfd == -1)             // 创建失败
        {
            lg(FATAL, "epoll_create error: %s", strerror(errno));
        }
        else // 创建成功
        {
            lg(INFO, "epoll_create sucess, fd: %d", _epfd); // 创建成功查看对应文件描述符
        }
    }

    int EpollerWait(struct epoll_event revents[], int num)
    {
        // 等待操作在Epoll模型中为将就绪队列中的
        // 已就绪事件文件描述符拷贝至用户预设空间
        int n = epoll_wait(_epfd, revents, num, _timeout);
        return n;
    }

    int EpollerUpdate(int op, int sock, uint32_t event)
    {
        int n = 0;
        if (op == EPOLL_CTL_DEL)
        {
            // 删除操作
            n = epoll_ctl(_epfd, op, sock, nullptr); // 删除
            if (n != 0)
            {
                lg(WARNING, "delete epoll_ctl error");
            }
        }
        else
        {
            // 非删除操作即新增或修改
            struct epoll_event ev;
            ev.events = event;
            ev.data.fd = sock;

            n = epoll_ctl(_epfd, op, sock, &ev); // 注册进内核
            if (n != 0)
            {
                lg(WARNING, "EpollerUpdate Error: %s", strerror(errno));
            }
        }
        return n;
    }

    ~Epoller()
    {
        if (_epfd >= 0)
        {
            close(_epfd);
        }
    }

private:
    int _epfd; // Epoll 的描述符
    static const int _timeout = 3000;
};
